package servidor;



import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;

import javax.swing.JOptionPane;

import clasesBasicas.*;
import utilidad.*;

public class GestorPeticion implements Runnable{
	
	  final static String CRLF = "\r\n";
	 
	  private int estado=0;
	  SocketManager sockManager;
	  private Usuario userConectado;
	  private GestorBDUsuarios usuarioBD;
	  private GestorBDPlacas placasBD;
	  private String nombreUser;
	  private byte[] bytesFoto;
	  private String tempAccion, tempPlaca, tempVariable;
	  private FileInputStream fisfoto;
	  private DataOutputStream outfoto;
	  private int numBytes;
	  
	  



	// Constructor
	  public GestorPeticion(SocketManager sockMan) throws Exception {
	    sockManager = sockMan;
	    usuarioBD= new GestorBDUsuarios();
	    
	  }

	  // Implement the run() method of the Runnable interface.
	  @Override
	public void run() {
	    try {
	      procesarPeticion();
	    }
	    catch (Exception e) {
	      System.out.println(e);
	    }
	  }

	  private void procesarPeticion() throws Exception {
		  String requestLine = "";
		  String respuesta="";
		  ArrayList <String> listado= new ArrayList<String>();
		  //luego será si estado no es 4
		  while (estado!=4) {
			  System.out.println("Conexión...");
	          //Lectura de la frase enviada por el cliente
	          requestLine=sockManager.Leer();
	          System.out.println("RequestLine: " + requestLine);

	        //saco de la linea el comando y los parametros que se obtienen
	          StringTokenizer tokens = new StringTokenizer(requestLine);
	          String comando =tokens.nextToken();

	        //Como puede haber hasta 3 parametros en un comando, cojemos los que se pueda
	          String parametro1="";
	          String parametro2="";
	          String parametro3="";

	          if(tokens.hasMoreTokens()){
	          	parametro1 = tokens.nextToken();}
	          if(tokens.hasMoreTokens()){
	          	parametro2 = tokens.nextToken();}
	          if(tokens.hasMoreTokens()){
	          	parametro3 = tokens.nextToken();}

	          
	          String obtenido="Comando: "+ comando;
	          if(!parametro1.equals(""))
	          {
	        	  obtenido=obtenido+" Parametro1: "+parametro1;
	          }
	          if(!parametro2.equals(""))
	          {
	        	  obtenido=obtenido+" Parametro2: "+parametro2;
	          }
	          if(!parametro3.equals(""))
	          {
	        	  obtenido=obtenido+" Parametro3: "+parametro3;
	        	  while(tokens.hasMoreTokens())
	        	  {
	        		  parametro3=parametro3+" "+tokens.nextToken();
	        	  }
	          }
	        
	          System.out.println("Incoming!!!");
	          System.out.println("1.............." + requestLine);
	          System.out.println("/"+parametro1+"/");
	          //Opciones segun estado
	          
	          switch(estado)
	          {
	          case 0:
	        	  //comprobar usuario con bd o falta nombre de usuario
	        	  if(parametro1.equals(""))
	        	  {
	        		  respuesta="400 ERR Falta el nombre de Usuario";
	        	  }
	        	  else
	        	  {
	        		  String usuariotemp=parametro1;
	        		  int resp=usuarioBD.comprobarUsuario(usuariotemp);
	        		  if(resp==1)
	        		  {
	        			  respuesta="200 OK Bienvenido "+usuariotemp;
	        			  nombreUser=usuariotemp;
	        			  estado=1;
	        			  Thread actual=Thread.currentThread();
	        			  actual.setName(nombreUser);
	        		  }
	        		  else
	        		  {
	        			  respuesta="401 ERR Usuario desconocido";
	        		  }
	        	  }
	          	break;
	          case 1:
	        	  
	        	  if(parametro1.equals(""))
	        	  {
	        		  respuesta="402 ERR falta la clave";
	        	  }
	        	  else
	        	  {
	        		  String pass=parametro1;
	        		  Usuario u= new Usuario(nombreUser, pass);
	        		  int resp= usuarioBD.comprobarUsuarioConPass(u);
	        		  if(resp==1)
	        		  {
	        				  respuesta="201 Ok Bienvenido al sistema";
	        				  userConectado=u;
	        				  estado=2;
	        				  placasBD= new GestorBDPlacas(usuarioBD.getConexion());
	        				  Servidor.vS.panelPrincipal.actualizarTabla();
	        		  }
	        		  else
	        		  {
	        			  respuesta="401 ERR La clave es incorrecta";
	        			  estado=0;
	        		  }
	        	  }
	          	break;
	          case 2:
		        	  if(comando.equals("BUSCAR"))
		        	  {
		        		  //Buscar Placa con opción y patrón (BUSCAR)
		        		  String opcion=parametro1;
		        		  String patron=parametro2;
		        		  listado=placasBD.buscarPorOpcion(opcion, patron);
		        		  System.out.println("[SERVER]     Empiezo listado");
		        		  for(int i=0; i<listado.size();i++)
		        		  {
		        			  System.out.println(listado.get(i));
		        		  }
		        		  //recorro el array y creo el string a enviar.
		        		  
		        		  
		        	  }
		        	  else if(comando.equals("LISTADO"))
		        	  {
		        	  //Listar placas (LIST)
		        		   listado= placasBD.listarPlacas();
		        		  
		        	  }
		        	  else if(comando.equals("ON"))
		        	  {
		        		//Activar (ON)
			        	  	//Error: id_variable no existe (403) o id_variable ya está ON (404)
		        		  
		        		  String id_placa=parametro1;
		        		  String id_variable=parametro2;
		        		  boolean existe=placasBD.existeVariable(id_placa, id_variable);
		        		  System.out.println("[EXISTE?]:   "+existe);
		        		  if(existe)
		        		  {
		        			  int estado=placasBD.estadoVariable(id_placa, id_variable);
		        			  System.out.println("[ESTADO VARIABLE]     "+estado);
		        			  if(estado==1)
		        			  {
		        				  respuesta="404 ERROR id_variable en estado ON";
		        			  }
		        			  else //si esta a 0 es que está OFF, correcto!
		        			  {
		        				  int var=placasBD.activarVariable(id_placa, id_variable);
		        				  if(var!=0)
		        				  {
		        					  respuesta="203 OK Control de "+id_variable+" activo.";
		        				  }
		        				  else
		        				  {
		        					  System.out.println("[ERROR]     NO he conseguido actualizar");
		        					  respuesta="404 ERROR no funciona";
		        				  }
		        			  }
		        		  }
		        		  else
		        		  {
		        			  respuesta="403 ERROR id_variable no existe.";
		        		  }
		        		  
		        		  
		        	  }
		        	  else if(comando.equals("OFF"))
		        	  {
		        		//Desactivar (OFF)
			        	  	//Error: id_variable no existe (405) o id_variable ya está OFF (406)
		        		  String id_placa=parametro1;
		        		  String id_variable=parametro2;
		        		  if(placasBD.existeVariable(id_placa, id_variable))
		        		  {
		        			  int estado=placasBD.estadoVariable(id_placa, id_variable);
		        			  System.out.println("[ESTADO VARIABLE]     "+estado);
		        			  
		        			  if(estado==1)
		        			  {
		        				  placasBD.desactivarVariable(id_placa, id_variable);
		        				  respuesta="204 OK Control de "+id_variable+" desactivado.";
		        				  
		        			  }
		        			  else
		        			  {
		        				  
		        				  respuesta="406 ERROR id_variable en estado OFF";
		        			  }
		        		  }
		        		  else
		        		  {
		        			  respuesta="405 ERROR id_variable no existe.";
		        		  }
		        		  
		        	  }
		        	  else if(comando.equals("ACCION"))
		        	  {
		        		//ACCION: pasa a estado 3.
			        	  	//Error: id_variable no existe (407) o id_variable ya está OFF (408)
		        		  String id_placa=parametro1;
		        		  String id_variable=parametro2;
		        		  String accion=parametro3;
		        		  System.out.println("[LA ACCION ES: ] "+accion);
		        		  int estadotemp=placasBD.estadoPlaca(id_placa);
		        		  if(estadotemp==1)
		        		  {
		        			  if(placasBD.existeVariable(id_placa, id_variable))
		        			  {
			        			  int estado2=placasBD.estadoVariable(id_placa, id_variable);
			        			  if(estado2==1)
			        			  {
			        				  respuesta="205 OK Esperando confirmacion."; 
			        				  estado=3;
			        				  tempAccion=accion;
			        				  tempVariable=id_variable;
			        				  tempPlaca=id_placa;
			        				  
			        			  }
			        			  else
			        			  {
			        				  respuesta="408 ERROR id_variable en estado OFF.";
			        			  }
		        			  }
		        			  else
		        			  {
		        				  respuesta="407 ERROR id_variable no existe.";
		        			  }
		        		  }
		        		  else
		        		  {
		        			  respuesta="Estado de la placa OFF";
		        		  }
		        		  
		        	  }
		        	  else if(comando.equals("OBTENER_FOTO"))
		        	  {
		        		//OBTENER_FOTO: foto de la placa
			        	  	//Error: identificador no existe (403)
		        		String id_placa=parametro1;
		        		boolean existe=placasBD.existePlaca(id_placa);
		        		if(!existe)
		        		{
		        			respuesta="";
		        		}
		        		else
		        		{
		        			
		        			String path=placasBD.obtenerFoto(id_placa);
		        			//MIRAR LO DE ENVIAR UNA FOTO !!!!!
		        			path="imagenesServer/"+path;
		        			System.out.println(path);
		        			File archivo = new File(path);
		        			
		        			fisfoto = null;
		        		    boolean fileExists = true;
		        			try {
		        			      fisfoto = new FileInputStream(archivo);
		        			      numBytes=fisfoto.available();
		        			      outfoto = new DataOutputStream(sockManager.obtenerOutStream());
		        			    }
		        			    catch (FileNotFoundException e) {
		        			      fileExists = false;
		        			      System.out.println("[ERROR]    No hay foto");
		        			    }
		        		}
		        		  
		        		  
		        	  }
		        	  else if(comando.equals("OBTENER_ACCIONES"))
		        	  {
		        		  String id_placa=parametro1;
		        		  String id_variable=parametro2;
		        		  listado=placasBD.obtenerAcciones(id_placa, id_variable);
		        	  }
		        	  else if(comando.equals("SALIR"))
		        	  {
		        		//SALIR: estado 4.
		        		  estado=4;
		      			  usuarioBD.desconectarUsuario(userConectado.getUserName());
		      			  respuesta="208 OK Adiós";
		      			  Servidor.vS.panelPrincipal.actualizarTabla();
		        		  
		        	  }
		             break;
	          case 3:
	        	  //CONFIRMAR_ACCION / RECHAZAR_ACCION: vuelve a estado 2.
	        	  //CONFIRMAR_ACCION Error: faltan datos (409)
	        	  if(comando.equals("CONFIRMAR_ACCION"))
	        	  {
	        		  //cambiamos de la BD
	        		  String valor=parametro1;
	        		  if(!parametro1.equals(""))
	        		  {
	        			  int completado=placasBD.realizarAccion(tempPlaca, tempVariable, tempAccion, valor);
	        			  if(completado==0)
	        			  {
	        				  System.out.println("[ERROR]   ACCION NO REALIZADA");
	        			  }
	        			  else
	        			  {
	        				  System.out.println("[OK]   ACCION REALIZADA");
	        			  }
	        			  respuesta="206 OK Acción sobre el sensor confirmada";
	        			  estado=2;
	        		  }
	        		  else
	        		  {
	        			  respuesta="409 ERR Faltan datos"; 
	        		  }  
	        		  
	        	  }
	        	  else
	        	  {
	        		  if(comando.equals("RECHAZAR_ACCION"))
	        		  {
	        			  estado=2;
	        			  respuesta="207 OK Accion cancelada";
	        		  }
	        	  }
	          	break;
	          }
	        //Escritura en el Socket para el envio al cliente 
	          if(comando.equals("LISTADO") || comando.equals("OBTENER_ACCIONES") || comando.equals("BUSCAR"))
	          {
	        	  System.out.println("*************Acabo de entrar en listado************");
	        	  for(int i=0;i<listado.size();i++)
	        	  {
	        		  System.out.println(listado.get(i));
	        		  sockManager.Escribir(listado.get(i)+'\n');
	        	  }
	          }
	          else if(comando.equals("OBTENER_FOTO"))
	          {
	        	  respuesta="206 OK "+numBytes+" bytes transmitiendo";
	        	  sockManager.Escribir(respuesta+'\n');
	        	  //envio de la imagen byte a byte
    			  
	        		    byte[] buffer = new byte[1024];
	        		    int bytes = 0;
	        		    while(bytes!=-1){
	        		    	System.out.println("Me quedo aqui!!");
	        		    	sockManager.Escribir(buffer, bytes);  //Saca del fichero de mil veinti cuatro a mil veinticuatro.
	        		    	bytes = fisfoto.read(buffer);
	        		    }
	        	  //sockManager.Escribir("202 FOTO COMPLETADA"+'\n');    
	          }
	          else
	          {
	        	  System.out.println("[RESPUESTA]  "+respuesta);
	        	  sockManager.Escribir(respuesta+'\n');
	          }
	          
	      }
	    // Close streams and socket.
		  if(userConectado!=null)
		  {
		    sockManager.CerrarStreams();
		    sockManager.CerrarSocket();
		  }
	  }
	  
	  public void cerrarRunnable()
	  {
		  estado=4;
		  usuarioBD.desconectarUsuario(userConectado.getUserName());
		  try {
			sockManager.CerrarSocket();
			sockManager.CerrarStreams();
		} catch (IOException e) {
			System.out.println("[ERROR]     CIERRE SOCKET");
			e.printStackTrace();
		}
		  
		  userConectado=null;
	  }

}